package com.hdcircles.autoform.model.http;

import com.google.gson.Gson;
import com.hdcircles.autoform.app.Constants;
import com.hdcircles.autoform.model.bean.ChooseQuestionBean;
import com.hdcircles.autoform.model.bean.FormBean;
import com.hdcircles.autoform.model.bean.HttpBody;
import com.hdcircles.autoform.model.bean.MapData;
import com.hdcircles.autoform.model.bean.MapHttpBody;
import com.hdcircles.autoform.model.bean.QuestionBean;
import com.hdcircles.autoform.model.bean.User;
import com.hdcircles.autoform.model.bean.WelcomeBean;
import com.hdcircles.autoform.util.SystemUtil;
import com.orhanobut.logger.Logger;

import java.io.File;
import java.io.IOException;
import java.net.SocketTimeoutException;
import java.util.List;
import java.util.concurrent.TimeUnit;

import okhttp3.Cache;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import rx.Observable;

/**
 * Created by hdcircles on 2016/9/21.
 */

public class RetrofitHelper {
    private static OkHttpClient okHttpClient=null;

    private static Apis apiService=null;

    private static FormApis formApisService=null;

    private static TokenApis tokenApisService=null;

    private static MapApis mapApisService=null;

    private void init(){
        initOkHttp();
        apiService=getApiService();
        formApisService=getFormApisService();
        tokenApisService=getTokenApisService();
        mapApisService=getMapApisService();
    }

    public RetrofitHelper(){
        init();
    }


    private static void initOkHttp(){
        OkHttpClient.Builder builder=new OkHttpClient.Builder();
//        if (BuildConfig.DEBUG){
//            HttpLoggingInterceptor loggingInterceptor=new HttpLoggingInterceptor();
//            loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BASIC);
//            builder.addInterceptor(loggingInterceptor);
//        }
        File cacheFile=new File(Constants.PATH_CACHE);
        Cache cache=new Cache(cacheFile,1024*1024*50);
        Interceptor cacheInterceptor=new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request=chain.request();
                try {
                    Response response=chain.proceed(request);
                    if (!SystemUtil.isNetWorkConnected()){
                        int maxAge=0;
                        //有网络时不缓存，最大保存时长为0
                        response.newBuilder()
                                .header("Cache-Control","public,max-age="+maxAge)
                                .removeHeader("Pragma")
                                .build();
                    }else {
                        //无网络时，设置超时为4周
                        int maxStale=60*60*24*28;
                        response.newBuilder()
                                .header("Cache-Control","public,only-if-cached,max-stale="+maxStale)
                                .removeHeader("Pragma")
                                .build();
                    }
                    return response;
                }catch (SocketTimeoutException exception){
                    exception.printStackTrace();
                }
               return chain.proceed(request);

            }
        };
        Interceptor apiKey=new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request=chain.request();
                request=request.newBuilder()
                        .addHeader("apiKey",Constants.KEY_API)
                        .build();
                return chain.proceed(request);
            }
        };
        builder.addNetworkInterceptor(cacheInterceptor);
        builder.addInterceptor(cacheInterceptor);
//        builder.addInterceptor(apiKey);
        builder.cache(cache);
        //设置超时
        builder.connectTimeout(30, TimeUnit.SECONDS);
        builder.readTimeout(30,TimeUnit.SECONDS);
        builder.writeTimeout(30,TimeUnit.SECONDS);
        //错误重连
        builder.retryOnConnectionFailure(true);
        okHttpClient=builder.build();
    }
    public interface OnConnectionTimeoutListener {
        void onConnectionTimeout();
    }

    private Response onOnIntercept(Interceptor.Chain chain) throws IOException {
        try {
            Response response = chain.proceed(chain.request());
            String content = "";
            return response.newBuilder().body(ResponseBody.create(response.body().contentType(), content)).build();
        } catch (SocketTimeoutException exception) {
            exception.printStackTrace();
        }

        return chain.proceed(chain.request());
    }

    private static Apis getApiService(){
        Retrofit retrofit=new Retrofit.Builder()
                .baseUrl(Apis.HOST)
                .client(okHttpClient)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
        return retrofit.create(Apis.class);
    }

    private static FormApis getFormApisService(){
        Retrofit retrofit=new Retrofit.Builder()
                .baseUrl(FormApis.HOST)
                .client(okHttpClient)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
        return retrofit.create(FormApis.class);
    }
    private static TokenApis getTokenApisService(){
        Retrofit retrofit=new Retrofit.Builder()
                .baseUrl(TokenApis.HOST)
                .client(okHttpClient)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
        return retrofit.create(TokenApis.class);
    }

    private static MapApis getMapApisService(){
        Retrofit retrofit=new Retrofit.Builder()
                .baseUrl(MapApis.Host)
                .client(okHttpClient)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
        return retrofit.create(MapApis.class);
    }

    public Observable<WelcomeBean> fetchWelcomeInfo(String res){
        return apiService.getWelcomeInfo(res);
    }

    public Observable<HttpResponse<String>> login(User user){
        HttpBody body=new HttpBody();
        body.setOperation("AddUser");
        body.setUser(user);
        Logger.json(new Gson().toJson(body));
        return formApisService.addUser(body);
    }

    public Observable<HttpResponse<User>> getUser(String userEmail){
        HttpBody body=new HttpBody();
        body.setOperation("GetUserByEmail");
        body.setUserEmail(userEmail);
        return formApisService.getUserByEmail(body);
    }


    public Observable<HttpResponse<String>> updateUser(User user){
        HttpBody body=new HttpBody();
        body.setOperation("UpdateUser");
        body.setUser(user);
        return formApisService.updateUser(body);
    }

    public Observable<HttpResponse<List<User>>> getAllUsers(){
        HttpBody body=new HttpBody();
        body.setOperation("GetAllUser");
        Logger.json(new Gson().toJson(body));
        return formApisService.getAllUserList(body);
    }

    public Observable<HttpResponse<String>> saveForm(FormBean form){
        HttpBody body=new HttpBody();
        body.setOperation("AddForm");
        body.setForm(form);
        Logger.json(new Gson().toJson(body));
        return formApisService.saveForm(body);
    }

    public Observable<HttpResponse<List<FormBean>>> getFormList(FormBean form){
        HttpBody body=new HttpBody();
        body.setOperation("SelectForm");
        body.setForm(form);
        Logger.json(new Gson().toJson(body));
        return formApisService.getFormList(body);
    }

    public Observable<HttpResponse<List<FormBean>>> getSharedFormList(String userEmail){
        HttpBody body=new HttpBody();
        body.setOperation("SelectFormByEmail");
        body.setUserEmail(userEmail);
        Logger.json(new Gson().toJson(body));
        return formApisService.getFormList(body);
    }

    public Observable<HttpResponse<String>> updateForm(FormBean formBean){
        HttpBody body=new HttpBody();
        body.setOperation("UpdateForm");
        body.setForm(formBean);
        Logger.json(new Gson().toJson(body));
        return formApisService.updateForm(body);
    }

    public Observable<HttpResponse<List<QuestionBean>>> getQuestionByFormId(String formId){
        HttpBody body=new HttpBody();
        body.setOperation("GetQuestionByFormId");
        body.setForm_Id(formId);
        Logger.json(new Gson().toJson(body));
        return formApisService.getQuestionByFormId(body);
    }

    public Observable<HttpResponse<List<ChooseQuestionBean>>> getChooseBean(int questionId){
        HttpBody body=new HttpBody();
        body.setOperation("GetChooseQuestionByQuestionId");
        body.setQuestion_Id(questionId);
        Logger.json(new Gson().toJson(body));
        return formApisService.getChoose(body);
    }

    public Observable<HttpResponse<String>> getToken(){
        HttpBody body=new HttpBody();
        body.setOperation("FGT");
        return tokenApisService.getToken(body);
    }

    public Observable<HttpResponse<String>> shareForm(String formId,List<String> userEmailList){
        HttpBody body=new HttpBody();
        body.setForm_Id(formId);
        body.setOperation("AddUserForm");
        body.setUserEmailList(userEmailList);
        Logger.json(new Gson().toJson(body));
        return formApisService.shareForm(body);
    }


    //--------------------------------------MAP APIS--------------------------------------------

    public Observable<MapData> createMap(String name){
        MapHttpBody body=new MapHttpBody();
        body.setName(name);
        body.setKey("0518ce9693a2343aa49ff0248e8638ac");
        return mapApisService.createMap(body);
    }

    public Observable<MapData> createMapData(String tableId,String data){
        MapHttpBody body=new MapHttpBody();
        body.setLoctype("2");
        body.setKey("0518ce9693a2343aa49ff0248e8638ac");
        body.setData(data);
        body.setTableid(tableId);
        return mapApisService.createData(body);
    }

}
